---
title: "Python Web Development: A FastAPI Guide"
description: "An in-depth guide to Python's modern web framework, FastAPI, from the perspective of a JavaScript (Node.js/Express) developer."
---

## 1. Introduction

### From Express to FastAPI

As a JavaScript developer, you are likely very familiar with `Node.js` and `Express`. They are a powerful combination for building fast, scalable network applications. When you transition to Python, you will find that `FastAPI` is a very similar and equally powerful choice.

`FastAPI` is a modern, fast (high-performance) web framework for building APIs. Its design is inspired by `Flask` and `Express`, and it fully utilizes Python's type hints and asynchronous features.

**Core Concept Analogy**

| Python (FastAPI) | JavaScript (Express) | Main Function |
| --- | --- | --- |
| **FastAPI** | `Express` | Web framework core |
| **Uvicorn/Hypercorn** | `node` / `pm2` | Application server |
| **Pydantic Models** | Joi / Zod / Manual validation | Data validation and serialization |
| **Dependency Injection** | Middleware / Service classes | Managing dependencies and shared logic |
| **`async def`** | `async` function | Asynchronous request handling |

> 💡 **Learning Strategy**: Think of FastAPI as a "typed, async-first Express". Many concepts, such as routing, requests, responses, and middleware, will feel very familiar.

## 2. Your First FastAPI Application

Let's start with a classic "Hello, World!" example to compare the basic structure of `FastAPI` and `Express`.

<PythonEditor title="Hello, World: FastAPI vs. Express" compare={true}>
```javascript !! js
// JavaScript (Express)
// server.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello, World!');
});

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});
```

```python !! py
# Python (FastAPI)
# main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello, World!"}

# Run the server (in the command line):
# uvicorn main:app --reload
```
</PythonEditor>

## 3. Routing and Request Handling

### 3.1 Path Parameters

<PythonEditor title="Path Parameter Comparison" compare={true}>
```javascript !! js
// JavaScript (Express)
app.get('/items/:itemId', (req, res) => {
  const itemId = req.params.itemId;
  res.json({ item_id: itemId });
});
```

```python !! py
# Python (FastAPI)
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int):
    return {"item_id": item_id}
```
</PythonEditor>

### 3.2 Query Parameters

<PythonEditor title="Query Parameter Comparison" compare={true}>
```javascript !! js
// JavaScript (Express)
app.get('/items', (req, res) => {
  const skip = req.query.skip || 0;
  const limit = req.query.limit || 10;
  res.json({ skip, limit });
});
```

```python !! py
# Python (FastAPI)
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/")
def read_items(skip: int = 0, limit: int = 10):
    return {"skip": skip, "limit": limit}
```
</PythonEditor>

### 3.3 Request Body

`FastAPI` uses `Pydantic` models to define the request body, which makes data validation, serialization, and documentation generation very simple.

<PythonEditor title="Request Body Comparison" compare={true}>
```javascript !! js
// JavaScript (Express)
app.use(express.json());

app.post('/items', (req, res) => {
  const { name, price } = req.body;
  // Manual validation
  if (!name || !price) {
    return res.status(400).json({ error: 'Missing name or price' });
  }
  res.json({ name, price });
});
```

```python !! py
# Python (FastAPI)
from fastapi import FastAPI
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
    is_offer: bool | None = None

app = FastAPI()

@app.post("/items/")
def create_item(item: Item):
    return item
```
</PythonEditor>

## 4. Data Validation with Pydantic

`Pydantic` is one of the core advantages of `FastAPI`. It provides powerful data validation features, similar to `TypeScript`'s type system combined with runtime validation from `Zod` or `Joi`.

<PythonEditor title="Data Validation Comparison" compare={true}>
```typescript !! ts
// TypeScript (with Zod for runtime validation)
import { z } from 'zod';

const UserSchema = z.object({
  username: z.string().min(3),
  email: z.string().email(),
  age: z.number().optional(),
});

type User = z.infer<typeof UserSchema>;

function createUser(user: unknown): User {
  return UserSchema.parse(user);
}
```

```python !! py
# Python (with Pydantic)
from pydantic import BaseModel, Field, EmailStr

class User(BaseModel):
    username: str = Field(min_length=3)
    email: EmailStr
    age: int | None = None

def create_user(user_data: dict) -> User:
    return User(**user_data)
```
</PythonEditor>

## 5. Dependency Injection

`FastAPI`'s dependency injection system is very powerful, making it easy to manage shared logic like database connections, authentication, and authorization.

<PythonEditor title="Dependency Injection Comparison" compare={true}>
```javascript !! js
// JavaScript (Express middleware)
function getDb(req, res, next) {
  req.db = new Database();
  next();
}

function requireAuth(req, res, next) {
  if (!req.headers.authorization) {
    return res.status(401).send('Unauthorized');
  }
  req.user = getUserFromToken(req.headers.authorization);
  next();
}

app.get('/profile', getDb, requireAuth, (req, res) => {
  res.json({ user: req.user });
});
```

```python !! py
# Python (FastAPI dependencies)
from fastapi import Depends, FastAPI, HTTPException, status

app = FastAPI()

class Database:
    def __init__(self): ...

def get_db():
    db = Database()
    try:
        yield db
    finally:
        # close db connection
        pass

async def get_current_user(token: str = Depends(oauth2_scheme)):
    # ... (logic to get user from token)
    return user

@app.get("/profile")
async def read_profile(current_user: User = Depends(get_current_user), db: Database = Depends(get_db)):
    return {"user": current_user}
```
</PythonEditor>

## 6. Async Support

`FastAPI` is an async-first framework, making it easy to handle asynchronous tasks like database queries, API calls, etc.

<PythonEditor title="Async Handling Comparison" compare={true}>
```javascript !! js
// JavaScript (Express)
app.get('/data', async (req, res) => {
  try {
    const data = await fetch('https://api.example.com/data').then(r => r.json());
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: 'Failed to fetch data' });
  }
});
```

```python !! py
# Python (FastAPI)
import httpx
from fastapi import FastAPI

app = FastAPI()

@app.get("/data")
async def get_data():
    async with httpx.AsyncClient() as client:
        response = await client.get("https://api.example.com/data")
        response.raise_for_status()
        return response.json()
```
</PythonEditor>

## 7. Summary

`FastAPI` provides a familiar and powerful web development experience for Python developers coming from a `JavaScript/Express` background. By leveraging type hints, async, and dependency injection, `FastAPI` can help you build robust, high-performance APIs.

Now that you have mastered the basics of `FastAPI`, you can start building your own Python web applications!
